﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Toodledo.Model
{
    public class Task
    {
        #region TaskPriority enum

        public enum TaskPriority
        {
            Negative = -1,
            Low = 0,
            Medium = 1,
            High = 2,
            Top = 3
        }

        #endregion

        #region TaskRepeat enum

        public enum TaskRepeat
        {
            NoRepeat,
            Weekly,
            Monthly,
            Yearly,
            Daily,
            Biweekly,
            Bimonthly,
            HalfYearly,
            Quarterly,
            WithParent,
            Advanced = 50
        }

        #endregion

        #region TaskRepeatFrom enum

        public enum TaskRepeatFrom
        {
            DueDate = 0,
            CompletionDate = 100
        }

        #endregion

        #region TaskStatus enum

        public enum TaskStatus
        {
            None,
            NextAction,
            Active,
            Planning,
            Delegated,
            Waiting,
            Hold,
            Postponed,
            Someday,
            Canceled,
            Reference
        }

        #endregion

        private DateTime? _dueDate;
        private TimeSpan? _dueTime;
        private string _note;
        private int _reminder;
        private DateTime? _startDate;
        private TimeSpan? _startTime;

        public string Id { get; set; }

        public string Title { get; set; }

        public string Tag { get; set; }

        public string FolderId { get; set; }

        public string ContextId { get; set; }

        public string ParentTaskId { get; set; }

        public DateTime? DueDate
        {
            get { return _dueDate; }
            set
            {
                if (value.HasValue)
                {
                    _dueDate = value.Value.Date;
                    _dueTime = value.Value - value.Value.Date;
                }
            }
        }

        public DateTime? StartDate
        {
            get { return _startDate; }
            set
            {
                if (value.HasValue)
                {
                    _startDate = value.Value.Date;
                    _startTime = value.Value - value.Value.Date;
                }
            }
        }

        public TimeSpan? DueTime
        {
            get { return _dueTime; }
            set
            {
                if (value.HasValue && value.Value > new TimeSpan(1))
                    throw new ArgumentOutOfRangeException("value", "DueTime must be less than 1 day");
                _dueTime = value;
            }
        }

        public TimeSpan? StartTime
        {
            get { return _startTime; }
            set
            {
                if (value.HasValue && value.Value > new TimeSpan(1))
                    throw new ArgumentOutOfRangeException("value", "StartTime must be less than 1 day");
                _startTime = value;
            }
        }

        public int Reminder
        {
            get { return _reminder; }
            set
            {
                if (value < 0 || value > 43200)
                    throw new ArgumentOutOfRangeException("value", "Reminder value must be between 0 and 43200 minutes");
                var validValues = new[]
                                      {
                                          0, 15, 30, 45, 60, 90, 120, 180, 240, 1440, 2880, 4320, 5760, 7200, 8640, 10080,
                                          20160, 43200
                                      };
                _reminder = validValues.Contains(value) ? value : GetNearestValidValue(validValues, value);
            }
        }

        public TaskRepeat Repeat { get; set; }

        public TaskRepeatFrom RepeatFrom { get; set; }

        public string RepeatAdvance { get; set; }

        public TaskStatus Status { get; set; }

        public TaskPriority Priority { get; set; }

        public int? LengthInMinutes { get; set; }

        public bool Star { get; set; }

        public string Note
        {
            get { return _note.Replace("%3B", ";").Replace("%26", "&"); }
            set { _note = value.Replace("&", "%26").Replace(";", "%3B"); }
        }

        private static int GetNearestValidValue(IEnumerable<int> validValues, int value)
        {
            int minDiff = 0;
            int nearestValidValue = 0;
            foreach (int validValue in validValues)
            {
                int currentDiff = Math.Abs(validValue - value);
                if (minDiff > currentDiff)
                {
                    minDiff = currentDiff;
                    nearestValidValue = validValue;
                }
            }
            return nearestValidValue;
        }
    }
}